<template>
    <el-dialog v-model="visible" width="760px" :close-on-click-modal="false" class="auto-dialog">
        <!-- ✅ 自定义标题 -->
        <template #title>
            <div class="dialog-title">📡 监测数据自动导入控制</div>
        </template>

        <!-- ✅ 主体卡片 -->
        <el-card shadow="hover" class="main-card">

            <!-- ✅ 顶部状态栏 -->
            <div class="status-row">
                <div class="left">
                    <div class="status-label">当前状态：</div>
                    <el-tag :type="running ? 'success' : 'info'" size="large">
                        {{ running ? "运行中" : "已关闭" }}
                    </el-tag>
                    <div v-if="running" class="running-since">
                        已运行: {{ formatRunningTime }}
                    </div>
                </div>

                <el-button :type="running ? 'danger' : 'primary'" size="large" round @click="toggleRunning" :loading="stopping">
                    {{ running ? (stopping ? "停止中..." : "停止任务") : "启动任务" }}
                </el-button>
            </div>

            <!-- ✅ 参数回显 -->
            <el-descriptions title="任务配置" :column="1" size="small" class="config-box">
                <el-descriptions-item label="雷达数据文件夹">
                    {{ config.filepath || "未配置" }}
                </el-descriptions-item>
                <el-descriptions-item label="导入间隔（分钟）">
                    {{ config.interval || "-" }}
                </el-descriptions-item>
                <el-descriptions-item label="运行模式">
                    持续监控模式（持久化）
                </el-descriptions-item>
                <el-descriptions-item label="死锁防护">
                    启用重试机制
                </el-descriptions-item>
                <el-descriptions-item label="并发控制">
                    单文件串行处理
                </el-descriptions-item>
            </el-descriptions>

            <!-- ✅ 统计信息 -->
            <div class="stats-row">
                <el-statistic title="已导入文件" :value="importedCount" />
                <el-statistic title="失败文件" :value="failedCount" />
                <el-statistic title="扫描次数" :value="scanCount" />
                <el-statistic title="死锁重试" :value="deadlockRetryCount" />
                <el-statistic title="运行时间" :value="Math.floor(runningTime / 60)" suffix="分钟" />
            </div>

            <!-- ✅ 日志区域 -->
            <div class="log-panel">
                <div class="log-header">
                    <span class="log-title">运行日志：</span>
                    <div>
                        <el-button size="small" @click="clearLogs">清空日志</el-button>
                        <el-button size="small" @click="exportLogs" :disabled="logs.length === 0">导出日志</el-button>
                    </div>
                </div>
                <div class="log-content" ref="logBox">
                    <div v-for="(msg, idx) in logs" :key="idx" class="log-item">
                        {{ msg }}
                    </div>
                </div>
            </div>

        </el-card>
    </el-dialog>
</template>

<script setup>
import { ref, nextTick, computed, onMounted, onUnmounted } from "vue";
import axios from "axios";
import { ElMessage } from "element-plus";

const visible = ref(false);
const running = ref(false);
const stopping = ref(false);
const config = ref({});
const logs = ref([]);
let stopFlag = false;
const logBox = ref(null);

// 统计信息
const importedCount = ref(0);
const failedCount = ref(0);
const scanCount = ref(0);
const runningTime = ref(0);
const deadlockRetryCount = ref(0); // 死锁重试次数
const startTime = ref(null);

// 当前正在导入的文件信息
const currentImportingFile = ref(null);
const processingFiles = ref(new Set());

// 定时器
let runningTimer = null;

// ============================
// ✅ 计算属性
// ============================
const formatRunningTime = computed(() => {
    const hours = Math.floor(runningTime.value / 3600);
    const minutes = Math.floor((runningTime.value % 3600) / 60);
    const seconds = runningTime.value % 60;
    
    if (hours > 0) {
        return `${hours}小时${minutes}分钟${seconds}秒`;
    } else if (minutes > 0) {
        return `${minutes}分钟${seconds}秒`;
    } else {
        return `${seconds}秒`;
    }
});

// ============================
// ✅ 持久化存储键名
// ============================
const STORAGE_KEYS = {
    RUNNING_STATE: 'auto_import_running',
    LOGS: 'auto_import_logs',
    STATS: 'auto_import_stats',
    START_TIME: 'auto_import_start_time',
    PROCESSING_FILES: 'auto_import_processing_files'
};

// ============================
// ✅ 生命周期
// ============================
onMounted(() => {
    loadPersistedState();
    runningTimer = setInterval(() => {
        if (running.value) {
            runningTime.value++;
            if (runningTime.value % 10 === 0) {
                savePersistedState();
            }
        }
    }, 1000);
});

onUnmounted(() => {
    if (runningTimer) {
        clearInterval(runningTimer);
    }
});

// ============================
// ✅ 持久化状态管理
// ============================
const loadPersistedState = () => {
    try {
        const savedRunning = localStorage.getItem(STORAGE_KEYS.RUNNING_STATE);
        if (savedRunning === 'true') {
            running.value = true;
            addLog("🔄 检测到之前运行的自动导入任务，正在恢复...");
            
            const savedStats = localStorage.getItem(STORAGE_KEYS.STATS);
            if (savedStats) {
                const stats = JSON.parse(savedStats);
                importedCount.value = stats.importedCount || 0;
                failedCount.value = stats.failedCount || 0;
                scanCount.value = stats.scanCount || 0;
                runningTime.value = stats.runningTime || 0;
                deadlockRetryCount.value = stats.deadlockRetryCount || 0;
            }
            
            const savedLogs = localStorage.getItem(STORAGE_KEYS.LOGS);
            if (savedLogs) {
                logs.value = JSON.parse(savedLogs);
            }

            const savedProcessingFiles = localStorage.getItem(STORAGE_KEYS.PROCESSING_FILES);
            if (savedProcessingFiles) {
                processingFiles.value = new Set(JSON.parse(savedProcessingFiles));
            }
            
            startAutoImport();
        }
    } catch (error) {
        console.error('加载持久化状态失败:', error);
    }
};

const savePersistedState = () => {
    try {
        localStorage.setItem(STORAGE_KEYS.RUNNING_STATE, running.value.toString());
        
        const stats = {
            importedCount: importedCount.value,
            failedCount: failedCount.value,
            scanCount: scanCount.value,
            runningTime: runningTime.value,
            deadlockRetryCount: deadlockRetryCount.value
        };
        localStorage.setItem(STORAGE_KEYS.STATS, JSON.stringify(stats));
        
        const recentLogs = logs.value.slice(-50);
        localStorage.setItem(STORAGE_KEYS.LOGS, JSON.stringify(recentLogs));

        localStorage.setItem(STORAGE_KEYS.PROCESSING_FILES, JSON.stringify([...processingFiles.value]));
    } catch (error) {
        console.error('保存持久化状态失败:', error);
    }
};

const clearPersistedState = () => {
    Object.values(STORAGE_KEYS).forEach(key => {
        localStorage.removeItem(key);
    });
};

// ============================
// ✅ 对话框控制
// ============================
const open = async () => {
    visible.value = true;
    await loadConfig();
};

const close = () => {
    visible.value = false;
};

// ============================
// ✅ 日志处理
// ============================
const addLog = msg => {
    const timestamp = new Date().toLocaleTimeString();
    logs.value.push(`${timestamp}  ${msg}`);

    if (logs.value.length > 200) {
        logs.value = logs.value.slice(-100);
    }

    nextTick(() => {
        if (logBox.value) logBox.value.scrollTop = logBox.value.scrollHeight;
    });
    
    savePersistedState();
};

const clearLogs = () => {
    logs.value = [];
    addLog("🗑️ 日志已清空");
};

const exportLogs = () => {
    const logText = logs.value.join('\n');
    const blob = new Blob([logText], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `自动导入日志_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.txt`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    addLog("📥 日志已导出");
};

// ============================
// ✅ delay函数
// ============================
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// ============================
// ✅ 读取 set_filepath 配置
// ============================
async function loadConfig() {
    try {
        const res = await axios.get("/set_filepath/");
        config.value = res.data;
    } catch {
        config.value = {};
    }
}

// ============================
// ✅ 启动/停止按钮
// ============================
const toggleRunning = async () => {
    if (running.value) {
        stopping.value = true;
        stopFlag = true;
        addLog("⏳ 正在停止任务，请等待当前文件导入完成...");
        
        let waitCount = 0;
        while (currentImportingFile.value && waitCount < 60) {
            await delay(1000);
            waitCount++;
            if (waitCount % 10 === 0) {
                addLog(`⏳ 等待当前文件导入完成... (${waitCount}/60秒)`);
            }
        }
        
        running.value = false;
        stopping.value = false;
        addLog("🛑 任务已安全停止");
        clearPersistedState();
    } else {
        stopFlag = false;
        running.value = true;
        startTime.value = new Date();
        runningTime.value = 0;
        processingFiles.value.clear();
        addLog("✅ 自动导入任务已启动（持久化模式）");
        addLog("💾 状态已保存，刷新页面不会中断任务");
        addLog("🛡️ 启用死锁防护和重试机制");
        startAutoImport();
    }
    
    savePersistedState();
};

// ===================================================
// ✅ 死锁防护的自动导入
// ===================================================
async function startAutoImport() {
    try {
        await loadConfig();

        const folder = config.value.filepath;
        const interval = config.value.interval || 1;

        addLog(`📁 监控文件夹 = ${folder}`);
        addLog(`⏱️ 扫描间隔 = ${interval} 分钟`);
        addLog("🛡️ 启用死锁防护：单文件串行处理 + 重试机制");

        if (!folder) {
            addLog("❌ 未配置雷达监测数据文件夹路径");
            running.value = false;
            savePersistedState();
            return;
        }

        // 持续监控循环
        while (running.value && !stopFlag) {
            scanCount.value++;
            addLog(`\n🔍 第 ${scanCount.value} 次扫描文件夹...`);

            try {
                // 扫描文件夹
                const listRes = await axios.get("/list_radar_folder_files/");
                let allFiles = listRes.data.files || [];

                if (allFiles.length === 0) {
                    addLog("📭 文件夹为空");
                } else {
                    addLog(`📄 扫描到 ${allFiles.length} 个文件`);
                }

                // 获取已导入文件清单
                const importedRes = await axios.get("/get_filelist/");
                const importedNames = importedRes.data.files.map(f => f.filename);

                // 排除已导入文件和处理中的文件
                allFiles = allFiles.filter(f => 
                    !importedNames.includes(f.filename) && 
                    !processingFiles.value.has(f.filename)
                );

                if (allFiles.length === 0) {
                    addLog("✅ 没有需要导入的新文件");
                    addLog(`⏳ 等待 ${interval} 分钟后重新扫描...`);
                    await waitWithCheck(interval * 60 * 1000);
                    continue;
                }

                addLog(`🎯 发现 ${allFiles.length} 个待导入文件`);

                // 排序（按修改时间，从旧到新）
                allFiles.sort((a, b) => new Date(a.modified) - new Date(b.modified));

                // ✅ 死锁防护：单文件串行处理，避免并发
                let currentBatchImported = 0;
                let currentBatchFailed = 0;

                for (const file of allFiles) {
                    if (stopFlag || !running.value) {
                        addLog("🛑 任务已停止");
                        return;
                    }

                    // 检查文件是否已经在处理中
                    if (processingFiles.value.has(file.filename)) {
                        addLog(`⏭️ 跳过正在处理中的文件：${file.filename}`);
                        continue;
                    }

                    currentImportingFile.value = file.filename;
                    processingFiles.value.add(file.filename);
                    
                    addLog(`➡️ 开始导入：${file.filename}`);
                    addLog(`📂 文件路径：${file.fullpath}`);

                    const importResult = await importFileWithDeadlockProtection(file);
                    
                    if (importResult.success) {
                        importedCount.value++;
                        currentBatchImported++;
                    } else {
                        failedCount.value++;
                        currentBatchFailed++;
                    }

                    // 清除当前导入文件状态
                    currentImportingFile.value = null;
                    processingFiles.value.delete(file.filename);
                    savePersistedState();

                    // ✅ 重要：文件间较长延迟，避免数据库资源竞争
                    addLog("⏳ 文件间延迟 10 秒，避免数据库死锁...");
                    await waitWithCheck(10000);
                }

                addLog(`📦 当前批次完成：成功 ${currentBatchImported} 个，失败 ${currentBatchFailed} 个`);
                savePersistedState();

            } catch (error) {
                console.error('扫描文件夹错误:', error);
                addLog(`❌ 扫描文件夹失败: ${error.message}`);
            }

            // 所有文件处理完成后，等待指定间隔再扫描
            addLog(`⏳ 等待 ${interval} 分钟后重新扫描新文件...`);
            await waitWithCheck(interval * 60 * 1000);
        }

        addLog("🎉 自动导入任务已结束");
        running.value = false;
        savePersistedState();

    } catch (err) {
        console.error('自动导入流程错误:', err);
        addLog("❌ 自动导入过程中发生错误");
        addLog(`错误详情：${err.message}`);
        running.value = false;
        savePersistedState();
    }
}

// ============================
// ✅ 带死锁防护的文件导入
// ============================
async function importFileWithDeadlockProtection(file) {
    const maxRetries = 3; // 最大重试次数
    const baseDelay = 5000; // 基础延迟5秒
    
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
            const formData = new FormData();
            formData.append('filepath', file.fullpath);
            formData.append('filetime', file.modified);

            const startTime = Date.now();
            
            const response = await axios.post("/upload_radar_data/", formData, {
                timeout: 300000, // 300秒超时
                headers: {
                    'Content-Type': 'multipart/form-data'
                }
            });

            const importTime = Math.round((Date.now() - startTime) / 1000);
            
            if (response.data) {
                addLog(`✅ 导入成功：${file.filename} (耗时: ${importTime}秒)`);
                addLog(`📊 响应信息：${response.data.message || '无详细信息'}`);
                return { success: true, time: importTime };
            } else {
                addLog(`⚠️ 导入完成但无响应数据：${file.filename}`);
                return { success: false, error: '无响应数据' };
            }

        } catch (err) {
            const importTime = Math.round((Date.now() - startTime) / 1000);
            
            // ✅ 检测死锁错误
            const isDeadlock = err.response?.status === 500 && 
                              err.response?.data?.error?.includes('死锁') ||
                              err.response?.data?.error?.includes('deadlock');
            
            if (isDeadlock && attempt < maxRetries) {
                deadlockRetryCount.value++;
                const retryDelay = baseDelay * attempt; // 递增延迟
                addLog(`🔄 检测到死锁，第 ${attempt}/${maxRetries} 次重试 (延迟 ${retryDelay/1000}秒)`);
                addLog("💡 正在等待数据库资源释放...");
                
                await delay(retryDelay);
                continue; // 继续重试
            }
            
            // 其他错误或重试次数用尽
            console.error(`导入错误 (尝试 ${attempt}):`, err);
            
            if (err.code === 'ECONNABORTED' || err.message.includes('timeout')) {
                addLog(`⏰ 导入超时：${file.filename} (已等待 ${importTime}秒)`);
            } else if (err.response) {
                addLog(`❌ 服务器错误 (${err.response.status}): ${err.response.data?.error || err.response.data?.message || '未知错误'}`);
            } else if (err.request) {
                addLog(`❌ 网络错误：无法连接到服务器`);
            } else {
                addLog(`❌ 导入失败：${err.message}`);
            }
            
            return { success: false, error: err.message };
        }
    }
    
    addLog(`❌ 文件 ${file.filename} 经过 ${maxRetries} 次重试后仍失败`);
    return { success: false, error: '重试次数用尽' };
}

// ============================
// ✅ 带停止检查的等待函数
// ============================
async function waitWithCheck(ms) {
    const checkInterval = 1000;
    const totalChecks = Math.ceil(ms / checkInterval);
    
    for (let i = 0; i < totalChecks; i++) {
        if (stopFlag || !running.value) {
            return;
        }
        await delay(checkInterval);
    }
}

defineExpose({ open, close });
</script>

<style scoped>
.auto-dialog :deep(.el-dialog) {
    border-radius: 12px;
    padding-bottom: 10px;
}

.dialog-title {
    font-size: 20px;
    font-weight: bold;
    color: #1f2d3d;
}

.main-card {
    border-radius: 12px;
}

.status-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.left {
    display: flex;
    align-items: center;
    gap: 15px;
}

.status-label {
    font-size: 16px;
    font-weight: 600;
}

.running-since {
    font-size: 12px;
    color: #666;
    background: #f0f0f0;
    padding: 4px 8px;
    border-radius: 4px;
}

.config-box {
    margin-bottom: 20px;
}

.stats-row {
    display: flex;
    justify-content: space-around;
    margin-bottom: 20px;
    padding: 15px;
    background: #f8f9fa;
    border-radius: 8px;
    flex-wrap: wrap;
    gap: 10px;
}

.stats-row :deep(.el-statistic) {
    text-align: center;
    min-width: 120px;
}

.stats-row :deep(.el-statistic__number) {
    font-size: 20px;
    font-weight: bold;
}

.log-panel {
    background: #111;
    padding: 12px;
    border-radius: 8px;
}

.log-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
}

.log-title {
    color: #e5e5e5;
    font-weight: bold;
}

.log-content {
    height: 240px;
    overflow-y: auto;
    background: #000;
    padding: 10px;
    border-radius: 6px;
    font-family: "Consolas", monospace;
}

.log-item {
    color: #7fff7f;
    padding: 2px 0;
    line-height: 1.4;
    white-space: pre-wrap;
}
</style>